Idé: eigen value compression för att få fram bakgrund
MVP: - Bakgrundsmodel 1. Average över frames, differencing / threshold 2. Gaussian, över sigma 3. Frame differencing - Priors 1. Uniform 2. Parametrisk x, y, k, size från heat map 3. Conditional på förra framen - Likelihood 1. Rektangel överlapp 2. Ellips överlapp - Accuracy - Över frames
library(jpeg)
jj <- readJPEG("./mall_dataset/frames/seq_000001.jpg",native=FALSE)
plot(0:1,0:1,type="n",ann=FALSE,axes=FALSE)
w <- 640
h <- 480
jj[seq(100, 1000)] = rep(1, 901)
jj[seq(100, 1000) + w*h] = rep(0, 901)
jj[seq(100, 1000) + 2*w*h] = rep(0, 901)
rasterImage(jj,0,0,1,1)
library(rmatio)
ground_truth <- read.mat("./mall_dataset/mall_gt.mat")
# ground_truth$frame[[1]][[2000]]$loc[[1]][,1]
jj <- readJPEG("./mall_dataset/frames/seq_000001.jpg",native=FALSE)
plot(0:1,0:1,type="n",ann=FALSE,axes=FALSE)
rasterImage(jj,0,0,1,1)
points(ground_truth$frame[[1]][[1]]$loc[[1]][,1] / w, 1-ground_truth$frame[[1]][[1]]$loc[[1]][,2] / h)
jpgs <- list()
# frames <- 2000
frames <- 1000
# background <- rep(0, w*h*3)
background <- jj / frames
for (f in 2:frames) {
jpg <- readJPEG(paste("./mall_dataset/frames/seq_",strrep("0", 6-log10(f + 1)),f,".jpg", sep=""),native=FALSE)
# for (i in 1:(w*h*3)) {
for (i in 1:h) {
for (j in 1:w) {
for (c in 1:3) {
background[i, j, c] <- background[i, j, c] + jpg[i, j, c] / frames
}
}
}
}
for (i in 1:h) {
for (j in 1:w) {
for (c in 1:3) {
background[i, j, c] <- max(min(background[i, j, c], 1), 0)
}
}
}
plot(0:1,0:1,type="n",ann=FALSE,axes=FALSE)
# rasterImage(background,0,0,1,1)
rasterImage(background,0,0,1,1)
# jj <- readJPEG("./mall_dataset/frames/seq_000001.jpg",native=FALSE)
plot(0:1,0:1,type="n",ann=FALSE,axes=FALSE)
rasterImage(jj,0,0,1,1)
locs <- list()
for (f in 1:frames) {
points(ground_truth$frame[[1]][[f]]$loc[[1]][,1] / w, 1-ground_truth$frame[[1]][[f]]$loc[[1]][,2] / h)
}
jj <- readJPEG("./mall_dataset/frames/seq_000001.jpg",native=FALSE)
plot(0:1,0:1,type="n",ann=FALSE,axes=FALSE)
interp <- function(x) -20*x^7+70*x^6-84*x^5+35*x^4
for (i in 1:h) {
for (j in 1:w) {
# for (c in 1:3) {
# jj[i, j, c] <- max(min(jj[i, j, c] - background[i, j, c], 1), 0)
# jj[i, j, c] <- max(min(-(sum(jj[i, j, c(1,2,3)])/3 - sum(background[i, j, c(1,2,3)])/3), 1), 0)
# jj[i, j, c] <- max(min(mean(jj[i, j, c(1,2,3)]), 1), 0)
# jj[i, j, c(1,2,3)] <- max(min(interp(1-(mean(jj[i, j, c(1,2,3)])-mean(background[i, j, c(1,2,3)]))), 1), 0)
jj[i, j, c(1,2,3)] <- max(min(
# ifelse(abs(mean(jj[i, j, c(1,2,3)])-mean(background[i, j, c(1,2,3)])) < 0.1, 0, mean(jj[i, j, c(1,2,3)]))
ifelse(abs(mean(jj[i, j, c(1,2,3)])-mean(background[i, j, c(1,2,3)])) < 0.1, 0, 1)
, 1), 0)
# }
}
}
rasterImage(jj,0,0,1,1)
# points(ground_truth$frame[[1]][[1]]$loc[[1]][,1] / w, 1-ground_truth$frame[[1]][[1]]$loc[[1]][,2] / h, col="red")
jj <- readJPEG("./mall_dataset/frames/seq_000001.jpg",native=FALSE)
plot(0:1,0:1,type="n",ann=FALSE,axes=FALSE)
rasterImage(jj,0,0,1,1)
plot(0:1,0:1,type="n",ann=FALSE,axes=FALSE)
rasterImage(background,0,0,1,1)
r <- c()
g <- c()
# frames <- 2000
frames <- 1000
i <- 200
j <- 300
# background <- rep(0, w*h*3)
for (f in 1:frames) {
jpg <- readJPEG(paste("./mall_dataset/frames/seq_",strrep("0", 6-log10(f + 1)),f,".jpg", sep=""),native=FALSE)
# for (i in 1:(w*h*3)) {
# for (i in 1:h) {
# for (j in 1:w) {
r <- c(r, jpg[i, j, 1])
g <- c(g, jpg[i, j, 2])
# }
# }
}
plot(r, g, xlim=c(0,1), ylim=c(0,1))
frames <- seq(1, 2000, by=2000/200)
frame_paths <- paste0("./mall_dataset/frames/seq_",strrep("0", 6-log10(frames + 1)),frames,".jpg")
# frames <- paste0("./mall_dataset/frames/seq_",strrep("0", 6-log10(1:100 + 1)),1:100,".jpg")
library(magick)
m <- image_read(frame_paths)
m <- image_animate(m)
image_write(m, "./movie10.gif")
library(jpeg)
jj <- readJPEG("./caviar_frames/ThreePastShop1cor0000.jpg",native=FALSE)
plot(0:1,0:1,type="n",ann=FALSE,axes=FALSE)
w <- 348
h <- 288
# jj[seq(100, 1000)] = rep(1, 901)
# jj[seq(100, 1000) + w*h] = rep(0, 901)
# jj[seq(100, 1000) + 2*w*h] = rep(0, 901)
rasterImage(jj,0,0,1,1)

library(XML)
# library(methods)
# f <- 500
# f <- 1200
for (f in round(seq(2, 1000, length.out = 100))) {
# jj <- readJPEG(paste("./caviar_frames/ThreePastShop1cor",strrep("0", 4-log10(f-1 + 1)),f-1,".jpg", sep=""), native=FALSE)
jj <- readJPEG(paste("./caviar_frames2/TwoEnterShop2cor",strrep("0", 4-log10(f-1 + 1)),f-1,".jpg", sep=""), native=FALSE)
# result <- xmlParse(file = "./c3ps1gt.xml")
result <- xmlParse(file = "./c2es2gt.xml")
# print(result)
plot(0:1,0:1,type="n",ann=FALSE,axes=FALSE)
rasterImage(jj,0,0,1,1)
rootnode <- xmlRoot(result)
is<-1:length(xmlElementsByTagName(rootnode[[f]][[1]], "object"))
for (i in is) {
attrs <- xmlAttrs(rootnode[[f]][[1]][[i]][[2]])
box <- list(
w=as.numeric(attrs["w"]),
h=as.numeric(attrs["h"]),
x=as.numeric(attrs["xc"]),
y=as.numeric(attrs["yc"]),
xy = c(as.numeric(attrs["xc"]), as.numeric(attrs["yc"]))
)
box
rect((box$x - box$w/2) / w, 1-(box$y - box$h/2) / h, (box$x + box$w/2)/w, 1-(box$y + box$h/2)/h)
}
}




































































































NA
NA
# rect((box$x-box$w/4) / w, 1-(box$y - box$h/2) / h, (box$x-box$w/4)/w, 1-(box$y + box$h/2)/h)
# points(box$x/w, 1-box$y/h, col="green")
# points((box$x-box$w)/w, 1-box$y/h, col="red")
# points((box$x-box$w/2)/w, 1-box$y/h, col="red")
# points((box$x+box$w)/w, 1-box$y/h, col="red")
# points((box$x+box$w/2)/w, 1-box$y/h, col="red")
#
# points((box$x)/w, 1-(box$y-box$h/2)/h, col="red")
# points((box$x)/w, 1-(box$y-box$h)/h, col="red")
# points((box$x)/w, 1-(box$y+box$h/2)/h, col="red")
# points((box$x)/w, 1-(box$y+box$h)/h, col="red")
#
# p1 <- c(91-10,163)
# # p2 <- c(91/w,163/h)
# p3 <- c(98-10,266)
# p4 <- c(322-10,265)
#
# points(p1[1]/w, 1-p1[2]/h, col="orange")
# points(p3[1]/w, 1-p3[2]/h, col="orange")
# points(p4[1]/w, 1-p4[2]/h, col="orange")
# Y <- (p1-p3)
# # Y <- (p3-p1)
# Y <- Y/norm(Y, type="2")
# X <- p4-p3
# X <- X/norm(X, type="2")
#
# # points(box$xy%*%X/w, 1-box$xy%*%Y/h, col="green")
# p <- box$x%*%X + box$y%*%Y
# points(p[1]/w, 1-p[2]/h, col="blue")
# lines(rep(0.5, 100), seq(0.01, 1, 0.01))
# pp <- c(seq(from=0*Y[1], to=1*Y[1], length.out = 100), seq(from=0*Y[2], to=1*Y[2], length.out = 100))
# # pp <- rep(0.5*X, 100) + c(seq(from=0*Y[1], to=1*Y[1], length.out = 100), seq(from=0*Y[2], to=1*Y[2], length.out = 100))
# lines(pp[seq(1, 200, by=2)], 1-pp[seq(2, 200, by=2)])
# %*%
# plot(0:1,0:1,type="n",ann=FALSE,axes=FALSE)
# for (t in seq(0, 1, by=0.01)) {
# t <- seq(0, h/2, by=0.01)
# s <- seq(0, w/2, by=0.01)
#
# for (t in seq(0, h/2, length.out = 20)) {
# for (s in seq(0, w/2, length.out = 20)) {
# p <- Y*t + X*s
# # p <- Y*t
# # points(p[1]/w + p3[1]/w, 1-(p[2] + p3[2])/h)
# points(p[1]/w, -(p[2])/h)
# # points(p[1]/w + p3[1]/w, 1-(Y[2]*t/h + p3[2])/h)
# # points(Y[1]*t/w+ p3[1]/w, 1-(Y[2]*t+ p3[2])/h)
# }
# }
# p <- X*box$x + Y*box$y
# # # p <- Y*t
# points(p[1]/w, -(p[2])/h, col="purple")
# points(0/w, h/h, col="purple")
# points(Y[1]*t/w+ p3[1]/w, 1-(Y[2]*t+ p3[2])/h)
# points(Y[1]*t/w+ p3[1]/w, 1-(Y[2]*t+ p3[2])/h)
# points(Y[1]*box$y/w+ p3[1]/w, 1-(Y[2]*box$y+ p3[2])/h)
# points(((p1-p3)[1]*t)/w, 1-((p1-p3)[2]*t)/h, col="green")
# }
# frames <- 2000
frames <- round(seq(2, 1600, length.out = 100))
# background <- rep(0, w*h*3)
jj <- readJPEG("./caviar_frames/ThreePastShop1cor0000.jpg",native=FALSE)
background <- jj / length(frames)
for (f in frames) {
# jj <- readJPEG(paste("./caviar_frames/ThreePastShop1cor",strrep("0", 4-log10(f-1 + 1)),f-1,".jpg", sep=""), native=FALSE)
jpg <- readJPEG(paste("./caviar_frames2/TwoEnterShop2cor",strrep("0", 4-log10(f-1 + 1)),f-1,".jpg", sep=""), native=FALSE)
# for (i in 1:(w*h*3)) {
for (i in 1:h) {
for (j in 1:w) {
for (c in 1:3) {
background[i, j, c] <- background[i, j, c] + jpg[i, j, c] / length(frames)
}
}
}
}
for (i in 1:h) {
for (j in 1:w) {
for (c in 1:3) {
background[i, j, c] <- max(min(background[i, j, c], 1), 0)
}
}
}
plot(0:1,0:1,type="n",ann=FALSE,axes=FALSE)
# rasterImage(background,0,0,1,1)
rasterImage(background,0,0,1,1)

for (f in round(seq(2, 1600, length.out = 10))) {
# jj <- readJPEG(paste("./caviar_frames/ThreePastShop1cor",strrep("0", 4-log10(f-1 + 1)),f-1,".jpg", sep=""), native=FALSE)
jj <- readJPEG(paste("./caviar_frames2/TwoEnterShop2cor",strrep("0", 4-log10(f-1 + 1)),f-1,".jpg", sep=""), native=FALSE)
plot(0:1,0:1,type="n",ann=FALSE,axes=FALSE)
rasterImage(jj,0,0,1,1)
interp <- function(x) -20*x^7+70*x^6-84*x^5+35*x^4
for (i in 1:h) {
for (j in 1:w) {
# for (c in 1:3) {
# jj[i, j, c] <- max(min(jj[i, j, c] - background[i, j, c], 1), 0)
# jj[i, j, c] <- max(min(-(sum(jj[i, j, c(1,2,3)])/3 - sum(background[i, j, c(1,2,3)])/3), 1), 0)
# jj[i, j, c] <- max(min(mean(jj[i, j, c(1,2,3)]), 1), 0)
# jj[i, j, c(1,2,3)] <- max(min(interp(1-(mean(jj[i, j, c(1,2,3)])-mean(background[i, j, c(1,2,3)]))), 1), 0)
jj[i, j, c(1,2,3)] <- max(min(
# ifelse(abs(mean(jj[i, j, c(1,2,3)])-mean(background[i, j, c(1,2,3)])) < 0.1, 0, mean(jj[i, j, c(1,2,3)]))
ifelse(abs(mean(jj[i, j, c(1,2,3)])-mean(background[i, j, c(1,2,3)])) < 0.2, 0, 1)
, 1), 0)
# }
}
}
plot(0:1,0:1,type="n",ann=FALSE,axes=FALSE)
rasterImage(jj,0,0,1,1)
# points(ground_truth$frame[[1]][[1]]$loc[[1]][,1] / w, 1-ground_truth$frame[[1]][[1]]$loc[[1]][,2] / h, col="red")
}




# library(methods)
# f <- 500
# f <- 1200
plot(0:1,0:1,type="n",ann=FALSE,axes=FALSE)
rasterImage(background,0,0,1,1)
result <- xmlParse(file = "./c2es2gt.xml")
rootnode <- xmlRoot(result)
for (f in round(seq(2, 1600, 1))) {
# jj <- readJPEG(paste("./caviar_frames/ThreePastShop1cor",strrep("0", 4-log10(f-1 + 1)),f-1,".jpg", sep=""), native=FALSE)
# jj <- readJPEG(paste("./caviar_frames2/TwoEnterShop2cor",strrep("0", 4-log10(f-1 + 1)),f-1,".jpg", sep=""), native=FALSE)
# result <- xmlParse(file = "./c3ps1gt.xml")
is<-1:length(xmlElementsByTagName(rootnode[[f]][[1]], "object"))
for (i in is) {
attrs <- xmlAttrs(rootnode[[f]][[1]][[i]][[2]])
box <- list(
w=as.numeric(attrs["w"]),
h=as.numeric(attrs["h"]),
x=as.numeric(attrs["xc"]),
y=as.numeric(attrs["yc"]),
xy = c(as.numeric(attrs["xc"]), as.numeric(attrs["yc"]))
)
# box
points(box$x/w, 1-box$y/h)
# rect((box$x - box$w/2) / w, 1-(box$y - box$h/2) / h, (box$x + box$w/2)/w, 1-(box$y + box$h/2)/h)
}
}

NA
NA
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpJZMOpOiBlaWdlbiB2YWx1ZSBjb21wcmVzc2lvbiBmw7ZyIGF0dCBmw6UgZnJhbSBiYWtncnVuZCANCg0KTVZQOg0KLSBCYWtncnVuZHNtb2RlbA0KICAxLiBBdmVyYWdlIMO2dmVyIGZyYW1lcywgZGlmZmVyZW5jaW5nIC8gdGhyZXNob2xkDQogIDIuIEdhdXNzaWFuLCDDtnZlciBzaWdtYQ0KICAzLiBGcmFtZSBkaWZmZXJlbmNpbmcNCi0gUHJpb3JzDQogIDEuIFVuaWZvcm0NCiAgMi4gUGFyYW1ldHJpc2sgeCwgeSwgaywgc2l6ZSBmcsOlbiBoZWF0IG1hcA0KICAzLiBDb25kaXRpb25hbCBww6UgZsO2cnJhIGZyYW1lbg0KLSBMaWtlbGlob29kDQogIDEuIFJla3RhbmdlbCDDtnZlcmxhcHANCiAgMi4gRWxsaXBzIMO2dmVybGFwcA0KLSBBY2N1cmFjeQ0KLSDDlnZlciBmcmFtZXMNCg0KDQoNCg0KYGBge3J9DQpsaWJyYXJ5KGpwZWcpDQpqaiA8LSByZWFkSlBFRygiLi9tYWxsX2RhdGFzZXQvZnJhbWVzL3NlcV8wMDAwMDEuanBnIixuYXRpdmU9RkFMU0UpDQpwbG90KDA6MSwwOjEsdHlwZT0ibiIsYW5uPUZBTFNFLGF4ZXM9RkFMU0UpDQoNCncgPC0gNjQwDQpoIDwtIDQ4MA0KDQpqaltzZXEoMTAwLCAxMDAwKV0gPSByZXAoMSwgOTAxKQ0Kampbc2VxKDEwMCwgMTAwMCkgKyB3KmhdID0gcmVwKDAsIDkwMSkNCmpqW3NlcSgxMDAsIDEwMDApICsgMip3KmhdID0gcmVwKDAsIDkwMSkNCg0KDQpyYXN0ZXJJbWFnZShqaiwwLDAsMSwxKQ0KYGBgDQoNCmBgYHtyfQ0KbGlicmFyeShybWF0aW8pDQpncm91bmRfdHJ1dGggPC0gcmVhZC5tYXQoIi4vbWFsbF9kYXRhc2V0L21hbGxfZ3QubWF0IikNCg0KDQojIGdyb3VuZF90cnV0aCRmcmFtZVtbMV1dW1syMDAwXV0kbG9jW1sxXV1bLDFdDQoNCmpqIDwtIHJlYWRKUEVHKCIuL21hbGxfZGF0YXNldC9mcmFtZXMvc2VxXzAwMDAwMS5qcGciLG5hdGl2ZT1GQUxTRSkNCnBsb3QoMDoxLDA6MSx0eXBlPSJuIixhbm49RkFMU0UsYXhlcz1GQUxTRSkNCg0KcmFzdGVySW1hZ2UoamosMCwwLDEsMSkNCg0KcG9pbnRzKGdyb3VuZF90cnV0aCRmcmFtZVtbMV1dW1sxXV0kbG9jW1sxXV1bLDFdIC8gdywgMS1ncm91bmRfdHJ1dGgkZnJhbWVbWzFdXVtbMV1dJGxvY1tbMV1dWywyXSAvIGgpDQpgYGANCg0KYGBge3J9DQpqcGdzIDwtIGxpc3QoKQ0KIyBmcmFtZXMgPC0gMjAwMA0KZnJhbWVzIDwtIDEwMDANCiMgYmFja2dyb3VuZCA8LSByZXAoMCwgdypoKjMpDQpiYWNrZ3JvdW5kIDwtIGpqIC8gZnJhbWVzDQpmb3IgKGYgaW4gMjpmcmFtZXMpIHsNCiAganBnIDwtIHJlYWRKUEVHKHBhc3RlKCIuL21hbGxfZGF0YXNldC9mcmFtZXMvc2VxXyIsc3RycmVwKCIwIiwgNi1sb2cxMChmICsgMSkpLGYsIi5qcGciLCBzZXA9IiIpLG5hdGl2ZT1GQUxTRSkNCiAgIyBmb3IgKGkgaW4gMToodypoKjMpKSB7DQogIGZvciAoaSBpbiAxOmgpIHsNCiAgICBmb3IgKGogaW4gMTp3KSB7DQogICAgICBmb3IgKGMgaW4gMTozKSB7DQogICAgICAgIGJhY2tncm91bmRbaSwgaiwgY10gPC0gYmFja2dyb3VuZFtpLCBqLCBjXSArIGpwZ1tpLCBqLCBjXSAvIGZyYW1lcw0KICAgICAgfQ0KICAgIH0NCiAgfQ0KfQ0KDQpmb3IgKGkgaW4gMTpoKSB7DQogIGZvciAoaiBpbiAxOncpIHsNCiAgICBmb3IgKGMgaW4gMTozKSB7DQogICAgICAgIGJhY2tncm91bmRbaSwgaiwgY10gPC0gbWF4KG1pbihiYWNrZ3JvdW5kW2ksIGosIGNdLCAxKSwgMCkNCiAgICB9DQogIH0NCn0NCnBsb3QoMDoxLDA6MSx0eXBlPSJuIixhbm49RkFMU0UsYXhlcz1GQUxTRSkNCiMgcmFzdGVySW1hZ2UoYmFja2dyb3VuZCwwLDAsMSwxKQ0KcmFzdGVySW1hZ2UoYmFja2dyb3VuZCwwLDAsMSwxKQ0KYGBgDQoNCmBgYHtyfQ0KIyBqaiA8LSByZWFkSlBFRygiLi9tYWxsX2RhdGFzZXQvZnJhbWVzL3NlcV8wMDAwMDEuanBnIixuYXRpdmU9RkFMU0UpDQpwbG90KDA6MSwwOjEsdHlwZT0ibiIsYW5uPUZBTFNFLGF4ZXM9RkFMU0UpDQoNCnJhc3RlckltYWdlKGpqLDAsMCwxLDEpDQoNCmxvY3MgPC0gbGlzdCgpDQoNCmZvciAoZiBpbiAxOmZyYW1lcykgew0KICBwb2ludHMoZ3JvdW5kX3RydXRoJGZyYW1lW1sxXV1bW2ZdXSRsb2NbWzFdXVssMV0gLyB3LCAxLWdyb3VuZF90cnV0aCRmcmFtZVtbMV1dW1tmXV0kbG9jW1sxXV1bLDJdIC8gaCkNCn0NCg0KDQpgYGANCg0KYGBge3J9DQpqaiA8LSByZWFkSlBFRygiLi9tYWxsX2RhdGFzZXQvZnJhbWVzL3NlcV8wMDAwMDEuanBnIixuYXRpdmU9RkFMU0UpDQpwbG90KDA6MSwwOjEsdHlwZT0ibiIsYW5uPUZBTFNFLGF4ZXM9RkFMU0UpDQoNCmludGVycCA8LSBmdW5jdGlvbih4KSAtMjAqeF43KzcwKnheNi04NCp4XjUrMzUqeF40DQoNCmZvciAoaSBpbiAxOmgpIHsNCiAgZm9yIChqIGluIDE6dykgew0KICAgICMgZm9yIChjIGluIDE6Mykgew0KICAgICAgICAjIGpqW2ksIGosIGNdIDwtIG1heChtaW4oampbaSwgaiwgY10gLSBiYWNrZ3JvdW5kW2ksIGosIGNdLCAxKSwgMCkNCiAgICAgICAgIyBqaltpLCBqLCBjXSA8LSBtYXgobWluKC0oc3VtKGpqW2ksIGosIGMoMSwyLDMpXSkvMyAtIHN1bShiYWNrZ3JvdW5kW2ksIGosIGMoMSwyLDMpXSkvMyksIDEpLCAwKQ0KICAgICAgICAjIGpqW2ksIGosIGNdIDwtIG1heChtaW4obWVhbihqaltpLCBqLCBjKDEsMiwzKV0pLCAxKSwgMCkNCiAgICAgICAgIyBqaltpLCBqLCBjKDEsMiwzKV0gPC0gbWF4KG1pbihpbnRlcnAoMS0obWVhbihqaltpLCBqLCBjKDEsMiwzKV0pLW1lYW4oYmFja2dyb3VuZFtpLCBqLCBjKDEsMiwzKV0pKSksIDEpLCAwKQ0KICAgICAgICBqaltpLCBqLCBjKDEsMiwzKV0gPC0gbWF4KG1pbigNCiAgICAgICAgICAjIGlmZWxzZShhYnMobWVhbihqaltpLCBqLCBjKDEsMiwzKV0pLW1lYW4oYmFja2dyb3VuZFtpLCBqLCBjKDEsMiwzKV0pKSA8IDAuMSwgMCwgbWVhbihqaltpLCBqLCBjKDEsMiwzKV0pKQ0KICAgICAgICAgIGlmZWxzZShhYnMobWVhbihqaltpLCBqLCBjKDEsMiwzKV0pLW1lYW4oYmFja2dyb3VuZFtpLCBqLCBjKDEsMiwzKV0pKSA8IDAuMSwgMCwgMSkNCiAgICAgICAgLCAxKSwgMCkNCiAgICAjIH0NCiAgfQ0KfQ0KDQpyYXN0ZXJJbWFnZShqaiwwLDAsMSwxKQ0KIyBwb2ludHMoZ3JvdW5kX3RydXRoJGZyYW1lW1sxXV1bWzFdXSRsb2NbWzFdXVssMV0gLyB3LCAxLWdyb3VuZF90cnV0aCRmcmFtZVtbMV1dW1sxXV0kbG9jW1sxXV1bLDJdIC8gaCwgY29sPSJyZWQiKQ0KYGBgDQpgYGB7cn0NCmpqIDwtIHJlYWRKUEVHKCIuL21hbGxfZGF0YXNldC9mcmFtZXMvc2VxXzAwMDAwMS5qcGciLG5hdGl2ZT1GQUxTRSkNCnBsb3QoMDoxLDA6MSx0eXBlPSJuIixhbm49RkFMU0UsYXhlcz1GQUxTRSkNCnJhc3RlckltYWdlKGpqLDAsMCwxLDEpDQoNCnBsb3QoMDoxLDA6MSx0eXBlPSJuIixhbm49RkFMU0UsYXhlcz1GQUxTRSkNCnJhc3RlckltYWdlKGJhY2tncm91bmQsMCwwLDEsMSkNCmBgYA0KDQpgYGB7cn0NCnIgPC0gYygpDQpnIDwtIGMoKQ0KIyBmcmFtZXMgPC0gMjAwMA0KZnJhbWVzIDwtIDEwMDANCmkgPC0gMjAwDQpqIDwtIDMwMA0KIyBiYWNrZ3JvdW5kIDwtIHJlcCgwLCB3KmgqMykNCmZvciAoZiBpbiAxOmZyYW1lcykgew0KICBqcGcgPC0gcmVhZEpQRUcocGFzdGUoIi4vbWFsbF9kYXRhc2V0L2ZyYW1lcy9zZXFfIixzdHJyZXAoIjAiLCA2LWxvZzEwKGYgKyAxKSksZiwiLmpwZyIsIHNlcD0iIiksbmF0aXZlPUZBTFNFKQ0KICAjIGZvciAoaSBpbiAxOih3KmgqMykpIHsNCiAgIyBmb3IgKGkgaW4gMTpoKSB7DQogICAgIyBmb3IgKGogaW4gMTp3KSB7DQoNCiAgICAgIHIgPC0gYyhyLCBqcGdbaSwgaiwgMV0pDQogICAgICBnIDwtIGMoZywganBnW2ksIGosIDJdKQ0KICAgICMgfQ0KICAjIH0NCn0NCg0KcGxvdChyLCBnLCB4bGltPWMoMCwxKSwgeWxpbT1jKDAsMSkpDQpgYGANCg0KYGBge3J9DQpmcmFtZXMgPC0gc2VxKDEsIDIwMDAsIGJ5PTIwMDAvMjAwKQ0KZnJhbWVfcGF0aHMgPC0gcGFzdGUwKCIuL21hbGxfZGF0YXNldC9mcmFtZXMvc2VxXyIsc3RycmVwKCIwIiwgNi1sb2cxMChmcmFtZXMgKyAxKSksZnJhbWVzLCIuanBnIikNCiMgZnJhbWVzIDwtIHBhc3RlMCgiLi9tYWxsX2RhdGFzZXQvZnJhbWVzL3NlcV8iLHN0cnJlcCgiMCIsIDYtbG9nMTAoMToxMDAgKyAxKSksMToxMDAsIi5qcGciKQ0KbGlicmFyeShtYWdpY2spDQptIDwtIGltYWdlX3JlYWQoZnJhbWVfcGF0aHMpDQptIDwtIGltYWdlX2FuaW1hdGUobSkNCmltYWdlX3dyaXRlKG0sICIuL21vdmllMTAuZ2lmIikNCmBgYA0KDQpgYGB7cn0NCmxpYnJhcnkoanBlZykNCmpqIDwtIHJlYWRKUEVHKCIuL2Nhdmlhcl9mcmFtZXMvVGhyZWVQYXN0U2hvcDFjb3IwMDAwLmpwZyIsbmF0aXZlPUZBTFNFKQ0KcGxvdCgwOjEsMDoxLHR5cGU9Im4iLGFubj1GQUxTRSxheGVzPUZBTFNFKQ0KDQp3IDwtIDM0OA0KaCA8LSAyODgNCg0KIyBqaltzZXEoMTAwLCAxMDAwKV0gPSByZXAoMSwgOTAxKQ0KIyBqaltzZXEoMTAwLCAxMDAwKSArIHcqaF0gPSByZXAoMCwgOTAxKQ0KIyBqaltzZXEoMTAwLCAxMDAwKSArIDIqdypoXSA9IHJlcCgwLCA5MDEpDQoNCg0KcmFzdGVySW1hZ2UoamosMCwwLDEsMSkNCmBgYA0KDQpgYGB7cn0NCmxpYnJhcnkoWE1MKQ0KIyBsaWJyYXJ5KG1ldGhvZHMpDQoNCiMgZiA8LSA1MDANCiMgZiA8LSAxMjAwDQpmb3IgKGYgaW4gcm91bmQoc2VxKDIsIDE2MDAsIGxlbmd0aC5vdXQgPSAxMDApKSkgew0KIyBqaiA8LSByZWFkSlBFRyhwYXN0ZSgiLi9jYXZpYXJfZnJhbWVzL1RocmVlUGFzdFNob3AxY29yIixzdHJyZXAoIjAiLCA0LWxvZzEwKGYtMSArIDEpKSxmLTEsIi5qcGciLCBzZXA9IiIpLCBuYXRpdmU9RkFMU0UpDQpqaiA8LSByZWFkSlBFRyhwYXN0ZSgiLi9jYXZpYXJfZnJhbWVzMi9Ud29FbnRlclNob3AyY29yIixzdHJyZXAoIjAiLCA0LWxvZzEwKGYtMSArIDEpKSxmLTEsIi5qcGciLCBzZXA9IiIpLCBuYXRpdmU9RkFMU0UpDQoNCiMgcmVzdWx0IDwtIHhtbFBhcnNlKGZpbGUgPSAiLi9jM3BzMWd0LnhtbCIpDQpyZXN1bHQgPC0geG1sUGFyc2UoZmlsZSA9ICIuL2MyZXMyZ3QueG1sIikNCg0KIyBwcmludChyZXN1bHQpDQoNCnBsb3QoMDoxLDA6MSx0eXBlPSJuIixhbm49RkFMU0UsYXhlcz1GQUxTRSkNCnJhc3RlckltYWdlKGpqLDAsMCwxLDEpDQoNCnJvb3Rub2RlIDwtIHhtbFJvb3QocmVzdWx0KQ0KaXM8LTE6bGVuZ3RoKHhtbEVsZW1lbnRzQnlUYWdOYW1lKHJvb3Rub2RlW1tmXV1bWzFdXSwgIm9iamVjdCIpKQ0KZm9yIChpIGluIGlzKSB7DQogIGF0dHJzIDwtIHhtbEF0dHJzKHJvb3Rub2RlW1tmXV1bWzFdXVtbaV1dW1syXV0pDQogIGJveCA8LSBsaXN0KA0KICAgIHc9YXMubnVtZXJpYyhhdHRyc1sidyJdKSwNCiAgICBoPWFzLm51bWVyaWMoYXR0cnNbImgiXSksDQogICAgeD1hcy5udW1lcmljKGF0dHJzWyJ4YyJdKSwNCiAgICB5PWFzLm51bWVyaWMoYXR0cnNbInljIl0pLA0KICAgIHh5ID0gYyhhcy5udW1lcmljKGF0dHJzWyJ4YyJdKSwgYXMubnVtZXJpYyhhdHRyc1sieWMiXSkpDQogICkNCiAgYm94DQogIA0KICByZWN0KChib3gkeCAtIGJveCR3LzIpIC8gdywgMS0oYm94JHkgLSBib3gkaC8yKSAvIGgsIChib3gkeCArIGJveCR3LzIpL3csIDEtKGJveCR5ICsgYm94JGgvMikvaCkNCn0NCg0KfQ0KDQoNCmBgYA0KDQpgYGB7cn0NCiMgcmVjdCgoYm94JHgtYm94JHcvNCkgLyB3LCAxLShib3gkeSAtIGJveCRoLzIpIC8gaCwgKGJveCR4LWJveCR3LzQpL3csIDEtKGJveCR5ICsgYm94JGgvMikvaCkNCiMgcG9pbnRzKGJveCR4L3csIDEtYm94JHkvaCwgY29sPSJncmVlbiIpDQojIHBvaW50cygoYm94JHgtYm94JHcpL3csIDEtYm94JHkvaCwgY29sPSJyZWQiKQ0KIyBwb2ludHMoKGJveCR4LWJveCR3LzIpL3csIDEtYm94JHkvaCwgY29sPSJyZWQiKQ0KIyBwb2ludHMoKGJveCR4K2JveCR3KS93LCAxLWJveCR5L2gsIGNvbD0icmVkIikNCiMgcG9pbnRzKChib3gkeCtib3gkdy8yKS93LCAxLWJveCR5L2gsIGNvbD0icmVkIikNCiMgDQojIHBvaW50cygoYm94JHgpL3csIDEtKGJveCR5LWJveCRoLzIpL2gsIGNvbD0icmVkIikNCiMgcG9pbnRzKChib3gkeCkvdywgMS0oYm94JHktYm94JGgpL2gsIGNvbD0icmVkIikNCiMgcG9pbnRzKChib3gkeCkvdywgMS0oYm94JHkrYm94JGgvMikvaCwgY29sPSJyZWQiKQ0KIyBwb2ludHMoKGJveCR4KS93LCAxLShib3gkeStib3gkaCkvaCwgY29sPSJyZWQiKQ0KIyANCiMgcDEgPC0gYyg5MS0xMCwxNjMpDQojICMgcDIgPC0gYyg5MS93LDE2My9oKQ0KIyBwMyA8LSBjKDk4LTEwLDI2NikNCiMgcDQgPC0gYygzMjItMTAsMjY1KQ0KIyANCiMgcG9pbnRzKHAxWzFdL3csIDEtcDFbMl0vaCwgY29sPSJvcmFuZ2UiKQ0KIyBwb2ludHMocDNbMV0vdywgMS1wM1syXS9oLCBjb2w9Im9yYW5nZSIpDQojIHBvaW50cyhwNFsxXS93LCAxLXA0WzJdL2gsIGNvbD0ib3JhbmdlIikNCg0KIyBZIDwtIChwMS1wMykNCiMgIyBZIDwtIChwMy1wMSkNCiMgWSA8LSBZL25vcm0oWSwgdHlwZT0iMiIpDQojIFggPC0gcDQtcDMNCiMgWCA8LSBYL25vcm0oWCwgdHlwZT0iMiIpDQojIA0KIyAjIHBvaW50cyhib3gkeHklKiVYL3csIDEtYm94JHh5JSolWS9oLCBjb2w9ImdyZWVuIikNCiMgcCA8LSBib3gkeCUqJVggKyBib3gkeSUqJVkNCiMgcG9pbnRzKHBbMV0vdywgMS1wWzJdL2gsIGNvbD0iYmx1ZSIpDQoNCiMgbGluZXMocmVwKDAuNSwgMTAwKSwgc2VxKDAuMDEsIDEsIDAuMDEpKQ0KDQojIHBwIDwtIGMoc2VxKGZyb209MCpZWzFdLCB0bz0xKllbMV0sIGxlbmd0aC5vdXQgPSAxMDApLCBzZXEoZnJvbT0wKllbMl0sIHRvPTEqWVsyXSwgbGVuZ3RoLm91dCA9IDEwMCkpDQojICMgcHAgPC0gcmVwKDAuNSpYLCAxMDApICsgYyhzZXEoZnJvbT0wKllbMV0sIHRvPTEqWVsxXSwgbGVuZ3RoLm91dCA9IDEwMCksIHNlcShmcm9tPTAqWVsyXSwgdG89MSpZWzJdLCBsZW5ndGgub3V0ID0gMTAwKSkNCiMgbGluZXMocHBbc2VxKDEsIDIwMCwgYnk9MildLCAxLXBwW3NlcSgyLCAyMDAsIGJ5PTIpXSkNCiMgJSolDQoNCiMgcGxvdCgwOjEsMDoxLHR5cGU9Im4iLGFubj1GQUxTRSxheGVzPUZBTFNFKQ0KIyBmb3IgKHQgaW4gc2VxKDAsIDEsIGJ5PTAuMDEpKSB7DQojIHQgPC0gc2VxKDAsIGgvMiwgYnk9MC4wMSkNCiMgcyA8LSBzZXEoMCwgdy8yLCBieT0wLjAxKQ0KIyANCiMgZm9yICh0IGluIHNlcSgwLCBoLzIsIGxlbmd0aC5vdXQgPSAyMCkpIHsNCiMgICBmb3IgKHMgaW4gc2VxKDAsIHcvMiwgbGVuZ3RoLm91dCA9IDIwKSkgew0KIyAgICAgcCA8LSBZKnQgKyBYKnMNCiMgICAgICMgcCA8LSBZKnQNCiMgICAgICMgcG9pbnRzKHBbMV0vdyArIHAzWzFdL3csIDEtKHBbMl0gKyBwM1syXSkvaCkNCiMgICAgIHBvaW50cyhwWzFdL3csIC0ocFsyXSkvaCkNCiMgICAgICMgcG9pbnRzKHBbMV0vdyArIHAzWzFdL3csIDEtKFlbMl0qdC9oICsgcDNbMl0pL2gpDQojICAgICAjIHBvaW50cyhZWzFdKnQvdysgcDNbMV0vdywgMS0oWVsyXSp0KyBwM1syXSkvaCkNCiMgICB9DQojIH0NCiMgcCA8LSBYKmJveCR4ICsgWSpib3gkeQ0KIyAjICMgcCA8LSBZKnQNCiMgcG9pbnRzKHBbMV0vdywgLShwWzJdKS9oLCBjb2w9InB1cnBsZSIpDQojIHBvaW50cygwL3csIGgvaCwgY29sPSJwdXJwbGUiKQ0KDQoNCiMgcG9pbnRzKFlbMV0qdC93KyBwM1sxXS93LCAxLShZWzJdKnQrIHAzWzJdKS9oKQ0KIyBwb2ludHMoWVsxXSp0L3crIHAzWzFdL3csIDEtKFlbMl0qdCsgcDNbMl0pL2gpDQojIHBvaW50cyhZWzFdKmJveCR5L3crIHAzWzFdL3csIDEtKFlbMl0qYm94JHkrIHAzWzJdKS9oKQ0KDQoNCiMgcG9pbnRzKCgocDEtcDMpWzFdKnQpL3csIDEtKChwMS1wMylbMl0qdCkvaCwgY29sPSJncmVlbiIpDQojIH0NCmBgYA0KDQpgYGB7cn0NCiMgZnJhbWVzIDwtIDIwMDANCmZyYW1lcyA8LSByb3VuZChzZXEoMiwgMTYwMCwgbGVuZ3RoLm91dCA9IDEwMCkpDQojIGJhY2tncm91bmQgPC0gcmVwKDAsIHcqaCozKQ0KamogPC0gcmVhZEpQRUcoIi4vY2F2aWFyX2ZyYW1lcy9UaHJlZVBhc3RTaG9wMWNvcjAwMDAuanBnIixuYXRpdmU9RkFMU0UpDQpiYWNrZ3JvdW5kIDwtIGpqIC8gbGVuZ3RoKGZyYW1lcykNCmZvciAoZiBpbiBmcmFtZXMpIHsNCiMgamogPC0gcmVhZEpQRUcocGFzdGUoIi4vY2F2aWFyX2ZyYW1lcy9UaHJlZVBhc3RTaG9wMWNvciIsc3RycmVwKCIwIiwgNC1sb2cxMChmLTEgKyAxKSksZi0xLCIuanBnIiwgc2VwPSIiKSwgbmF0aXZlPUZBTFNFKQ0KICBqcGcgPC0gcmVhZEpQRUcocGFzdGUoIi4vY2F2aWFyX2ZyYW1lczIvVHdvRW50ZXJTaG9wMmNvciIsc3RycmVwKCIwIiwgNC1sb2cxMChmLTEgKyAxKSksZi0xLCIuanBnIiwgc2VwPSIiKSwgbmF0aXZlPUZBTFNFKQ0KICAjIGZvciAoaSBpbiAxOih3KmgqMykpIHsNCiAgZm9yIChpIGluIDE6aCkgew0KICAgIGZvciAoaiBpbiAxOncpIHsNCiAgICAgIGZvciAoYyBpbiAxOjMpIHsNCiAgICAgICAgYmFja2dyb3VuZFtpLCBqLCBjXSA8LSBiYWNrZ3JvdW5kW2ksIGosIGNdICsganBnW2ksIGosIGNdIC8gbGVuZ3RoKGZyYW1lcykNCiAgICAgIH0NCiAgICB9DQogIH0NCn0NCg0KZm9yIChpIGluIDE6aCkgew0KICBmb3IgKGogaW4gMTp3KSB7DQogICAgZm9yIChjIGluIDE6Mykgew0KICAgICAgICBiYWNrZ3JvdW5kW2ksIGosIGNdIDwtIG1heChtaW4oYmFja2dyb3VuZFtpLCBqLCBjXSwgMSksIDApDQogICAgfQ0KICB9DQp9DQpwbG90KDA6MSwwOjEsdHlwZT0ibiIsYW5uPUZBTFNFLGF4ZXM9RkFMU0UpDQojIHJhc3RlckltYWdlKGJhY2tncm91bmQsMCwwLDEsMSkNCnJhc3RlckltYWdlKGJhY2tncm91bmQsMCwwLDEsMSkNCmBgYA0KDQpgYGB7cn0NCmZvciAoZiBpbiByb3VuZChzZXEoMiwgMTYwMCwgbGVuZ3RoLm91dCA9IDEwKSkpIHsNCiMgamogPC0gcmVhZEpQRUcocGFzdGUoIi4vY2F2aWFyX2ZyYW1lcy9UaHJlZVBhc3RTaG9wMWNvciIsc3RycmVwKCIwIiwgNC1sb2cxMChmLTEgKyAxKSksZi0xLCIuanBnIiwgc2VwPSIiKSwgbmF0aXZlPUZBTFNFKQ0KamogPC0gcmVhZEpQRUcocGFzdGUoIi4vY2F2aWFyX2ZyYW1lczIvVHdvRW50ZXJTaG9wMmNvciIsc3RycmVwKCIwIiwgNC1sb2cxMChmLTEgKyAxKSksZi0xLCIuanBnIiwgc2VwPSIiKSwgbmF0aXZlPUZBTFNFKQ0KcGxvdCgwOjEsMDoxLHR5cGU9Im4iLGFubj1GQUxTRSxheGVzPUZBTFNFKQ0KcmFzdGVySW1hZ2UoamosMCwwLDEsMSkNCg0KaW50ZXJwIDwtIGZ1bmN0aW9uKHgpIC0yMCp4XjcrNzAqeF42LTg0KnheNSszNSp4XjQNCg0KZm9yIChpIGluIDE6aCkgew0KICBmb3IgKGogaW4gMTp3KSB7DQogICAgIyBmb3IgKGMgaW4gMTozKSB7DQogICAgICAgICMgampbaSwgaiwgY10gPC0gbWF4KG1pbihqaltpLCBqLCBjXSAtIGJhY2tncm91bmRbaSwgaiwgY10sIDEpLCAwKQ0KICAgICAgICAjIGpqW2ksIGosIGNdIDwtIG1heChtaW4oLShzdW0oampbaSwgaiwgYygxLDIsMyldKS8zIC0gc3VtKGJhY2tncm91bmRbaSwgaiwgYygxLDIsMyldKS8zKSwgMSksIDApDQogICAgICAgICMgampbaSwgaiwgY10gPC0gbWF4KG1pbihtZWFuKGpqW2ksIGosIGMoMSwyLDMpXSksIDEpLCAwKQ0KICAgICAgICAjIGpqW2ksIGosIGMoMSwyLDMpXSA8LSBtYXgobWluKGludGVycCgxLShtZWFuKGpqW2ksIGosIGMoMSwyLDMpXSktbWVhbihiYWNrZ3JvdW5kW2ksIGosIGMoMSwyLDMpXSkpKSwgMSksIDApDQogICAgICAgIGpqW2ksIGosIGMoMSwyLDMpXSA8LSBtYXgobWluKA0KICAgICAgICAgICMgaWZlbHNlKGFicyhtZWFuKGpqW2ksIGosIGMoMSwyLDMpXSktbWVhbihiYWNrZ3JvdW5kW2ksIGosIGMoMSwyLDMpXSkpIDwgMC4xLCAwLCBtZWFuKGpqW2ksIGosIGMoMSwyLDMpXSkpDQogICAgICAgICAgaWZlbHNlKGFicyhtZWFuKGpqW2ksIGosIGMoMSwyLDMpXSktbWVhbihiYWNrZ3JvdW5kW2ksIGosIGMoMSwyLDMpXSkpIDwgMC4yLCAwLCAxKQ0KICAgICAgICAsIDEpLCAwKQ0KICAgICMgfQ0KICB9DQp9DQoNCnBsb3QoMDoxLDA6MSx0eXBlPSJuIixhbm49RkFMU0UsYXhlcz1GQUxTRSkNCnJhc3RlckltYWdlKGpqLDAsMCwxLDEpDQojIHBvaW50cyhncm91bmRfdHJ1dGgkZnJhbWVbWzFdXVtbMV1dJGxvY1tbMV1dWywxXSAvIHcsIDEtZ3JvdW5kX3RydXRoJGZyYW1lW1sxXV1bWzFdXSRsb2NbWzFdXVssMl0gLyBoLCBjb2w9InJlZCIpDQp9DQojIHBsb3QoMDoxLDA6MSx0eXBlPSJuIixhbm49RkFMU0UsYXhlcz1GQUxTRSkNCiMgcmFzdGVySW1hZ2UoYmFja2dyb3VuZCwwLDAsMSwxKQ0KYGBgDQoNCmBgYHtyfQ0KIyBsaWJyYXJ5KG1ldGhvZHMpDQoNCiMgZiA8LSA1MDANCiMgZiA8LSAxMjAwDQpwbG90KDA6MSwwOjEsdHlwZT0ibiIsYW5uPUZBTFNFLGF4ZXM9RkFMU0UpDQpyYXN0ZXJJbWFnZShiYWNrZ3JvdW5kLDAsMCwxLDEpDQoNCnJlc3VsdCA8LSB4bWxQYXJzZShmaWxlID0gIi4vYzJlczJndC54bWwiKQ0Kcm9vdG5vZGUgPC0geG1sUm9vdChyZXN1bHQpDQoNCmZvciAoZiBpbiByb3VuZChzZXEoMiwgMTYwMCwgMSkpKSB7DQojIGpqIDwtIHJlYWRKUEVHKHBhc3RlKCIuL2Nhdmlhcl9mcmFtZXMvVGhyZWVQYXN0U2hvcDFjb3IiLHN0cnJlcCgiMCIsIDQtbG9nMTAoZi0xICsgMSkpLGYtMSwiLmpwZyIsIHNlcD0iIiksIG5hdGl2ZT1GQUxTRSkNCiMgamogPC0gcmVhZEpQRUcocGFzdGUoIi4vY2F2aWFyX2ZyYW1lczIvVHdvRW50ZXJTaG9wMmNvciIsc3RycmVwKCIwIiwgNC1sb2cxMChmLTEgKyAxKSksZi0xLCIuanBnIiwgc2VwPSIiKSwgbmF0aXZlPUZBTFNFKQ0KDQojIHJlc3VsdCA8LSB4bWxQYXJzZShmaWxlID0gIi4vYzNwczFndC54bWwiKQ0KDQppczwtMTpsZW5ndGgoeG1sRWxlbWVudHNCeVRhZ05hbWUocm9vdG5vZGVbW2ZdXVtbMV1dLCAib2JqZWN0IikpDQpmb3IgKGkgaW4gaXMpIHsNCiAgYXR0cnMgPC0geG1sQXR0cnMocm9vdG5vZGVbW2ZdXVtbMV1dW1tpXV1bWzJdXSkNCiAgYm94IDwtIGxpc3QoDQogICAgdz1hcy5udW1lcmljKGF0dHJzWyJ3Il0pLA0KICAgIGg9YXMubnVtZXJpYyhhdHRyc1siaCJdKSwNCiAgICB4PWFzLm51bWVyaWMoYXR0cnNbInhjIl0pLA0KICAgIHk9YXMubnVtZXJpYyhhdHRyc1sieWMiXSksDQogICAgeHkgPSBjKGFzLm51bWVyaWMoYXR0cnNbInhjIl0pLCBhcy5udW1lcmljKGF0dHJzWyJ5YyJdKSkNCiAgKQ0KICAjIGJveA0KICANCiAgcG9pbnRzKGJveCR4L3csIDEtYm94JHkvaCkNCiAgDQogICMgcmVjdCgoYm94JHggLSBib3gkdy8yKSAvIHcsIDEtKGJveCR5IC0gYm94JGgvMikgLyBoLCAoYm94JHggKyBib3gkdy8yKS93LCAxLShib3gkeSArIGJveCRoLzIpL2gpDQp9DQoNCn0NCg0KDQpgYGA=